package com.lyhcc.software;

import com.lyhcc.utils.Calculator;
import com.lyhcc.utils.Fraction;
import com.lyhcc.utils.StackCal;

import java.util.ArrayList;
import java.util.Random;

public class MainCal {
    private int formularNum;        //算式的个数
    private int timeRestriction;    //限制完成的时间
    private int numMaxCount = 2;        //运算数最大个数
    private int numMinCount = 2;    //运算数最小个数
    private int bound = 100;        //生成算式的最大范围

    private static boolean[] isFraction = {true,false,true,false,true,false,false};         //是否为分数
    private static boolean[] hasParetheses = {true,false,false,true};      //是否有括号
    private final static char[] opArray = {'+','-','×','÷'};    // 运算符

    /**
     *
     * @param formularNum       算式的个数
     * @param timeRestriction   限制完成的时间
     * @param numMinCount       运算数最小个数
     * @param numMaxCount       运算数最大个数
     */
    public MainCal(int formularNum, int timeRestriction, int numMinCount, int numMaxCount,int bound) {
        this.formularNum = formularNum;
        this.timeRestriction = timeRestriction;
        this.numMaxCount = numMaxCount;
        this.numMinCount = numMinCount;
        this.bound = bound;
    }

    public MainCal(int formularNum, int bound) {
        this.formularNum = formularNum;
        this.bound = bound;
    }

    public MainCal(int formularNum) {
        this.formularNum = formularNum;
    }

    /**
     * 该方法用于生成相应数量的四则运算算式
     * @return
     */
    public ArrayList<String> formularBorn(){


        ArrayList<String> formualrList = new ArrayList<>();
        Random r = new Random();


        for (int i = 0; i < formularNum; i++) {
            born(formualrList, r);
        }

        return formualrList;
    }

    public void born(ArrayList<String> formualrList, Random r) {
        StringBuffer res = new StringBuffer();
        /*oneFormularNumcnt 为一个算式的运算数个数，他的范围在numMinCount ~ numMaxCount之间*/
        int oneFormularNumCnt;
        if(numMinCount == numMaxCount){
            oneFormularNumCnt = 2;
        }else {
            oneFormularNumCnt = r.nextInt(numMaxCount - numMinCount) + numMinCount;
        }

        int parethesesPos = r.nextInt(oneFormularNumCnt) - 1;
        //产生左括号的位置
        int lftParetheses = 1,rhtParetheses = 0;
        for(int j = 0; j<oneFormularNumCnt; j++){

            //随机产生括号位置
            if(j!=oneFormularNumCnt - 1 && lftParetheses+1 < j && hasParetheses[r.nextInt(4)]){
                lftParetheses = j;
                res.append('(');
                 rhtParetheses = j + 1;
            }


            //随机产生一个整数，如果此时要产生的数为分数,a为分母，否则为一个整数
            int a = r.nextInt(100)+1;
            //随机判断是否为分数，是分数就产生比a小的分子，即该分数为和真分数

            if(isFraction[r.nextInt(7)]){
                a = a==0?1:a;
                Fraction fraction = new Fraction(r.nextInt(a) + 1, a);
                Calculator.fractionToSimple(fraction);
                //如果分子分母相等，只把一个数翻入式子中
                if(fraction.getDenominator() == fraction.getMolecular()||a==1){
                    res.append(fraction.getMolecular());
                }else{
                    res.append(fraction.toString());
                }

            }else {
                res.append(Integer.toString(a));
            }


            //加入哟括号
            if(rhtParetheses!=0 && j == rhtParetheses){
                res.append(')');
            }

            //加入运算符
            if(j < oneFormularNumCnt - 1 ){
                res.append(opArray[r.nextInt(4)]);
            }
        }
        res.append('=');

        System.out.println(res);

        formualrList.add(res.toString());
    }

    /**
     * 该方法用于计算所有生成的算式的答案
     * @param list     算式链表
     *
     * @return
     */
    public ArrayList<Fraction> formularAnswer(ArrayList<String> list){
        ArrayList<Fraction> resList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            try {
                resList.add(StackCal.evaluateFormular(list.get(i)));
            } catch (Exception e) {
                list.remove(i);
                born(list,new Random());
            }
        }
        return  resList;
    }
}
